﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Text;

namespace Octopus.Injection.Commons.Interceptor
{
    internal class BaseInspector : IMessageSink
    {
        private IMessageSink _nextMsg;
        private MarshalByRefObject _realobject = null;

        internal BaseInspector(IMessageSink nextSink, MarshalByRefObject value)
        {
            _nextMsg = nextSink;
            _realobject = value;
        }

        public IMessageSink NextSink
        {
            get { return _nextMsg; }
        }

        public IMessage SyncProcessMessage(IMessage msg)
        {
            IMessage returnMethod = null;
            var aop = _realobject as AspectSupport;

            bool needPreaction = true;
            bool needPostaction = true;
            string typeName = _realobject.GetType().FullName ?? string.Empty;

            if (aop != null && aop.NeedPreAction.ContainsKey(typeName))
            {
                needPreaction = aop.NeedPreAction[typeName];
            }

            if (aop != null && needPreaction)
            {
                aop.NeedPreAction[typeName] = PreProcess(msg, _realobject);        
            }

            returnMethod = _nextMsg.SyncProcessMessage(msg);

            if (aop != null && aop.NeedPostAction.ContainsKey(typeName))
            {
                needPostaction = aop.NeedPostAction[typeName];
            }

            if (aop != null && needPostaction)
            {
                aop.NeedPostAction[typeName] = PostProcess(msg, returnMethod, _realobject);  
            }

            return returnMethod;
        }
                
        public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
        {
            throw new InvalidOperationException();
        }

        internal virtual bool PreProcess(IMessage msg, MarshalByRefObject value)
        {
            return false;
        }

        internal virtual bool PostProcess(IMessage msg, IMessage returnMethod, MarshalByRefObject value)
        {
            return false;
        }
    }
}
